package one.mixin.android.ui.conversation.holder

import android.graphics.Color
import android.util.TypedValue
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import one.mixin.android.Constants
import one.mixin.android.Constants.Colors.LINK_COLOR
import one.mixin.android.Constants.Colors.SELECT_COLOR
import one.mixin.android.R
import one.mixin.android.RxBus
import one.mixin.android.databinding.ItemChatTextQuoteBinding
import one.mixin.android.event.MentionReadEvent
import one.mixin.android.extension.defaultSharedPreferences
import one.mixin.android.extension.dp
import one.mixin.android.extension.dpToPx
import one.mixin.android.extension.initChatMode
import one.mixin.android.extension.maxItemWidth
import one.mixin.android.extension.renderMessage
import one.mixin.android.ui.conversation.adapter.MessageAdapter
import one.mixin.android.ui.conversation.holder.base.BaseMentionHolder
import one.mixin.android.ui.conversation.holder.base.Terminable
import one.mixin.android.util.GsonHelper
import one.mixin.android.util.mention.MentionRenderCache
import one.mixin.android.vo.MessageItem
import one.mixin.android.vo.QuoteMessageItem
import one.mixin.android.vo.isSecret
import one.mixin.android.widget.linktext.AutoLinkMode

class TextQuoteHolder constructor(val binding: ItemChatTextQuoteBinding) :
    BaseMentionHolder(binding.root),
    Terminable {
        private val dp16 = itemView.context.dpToPx(16f)

        init {
            binding.root.context.defaultSharedPreferences.getInt(Constants.Account.PREF_TEXT_SIZE, 14).apply {
                if (this != 14) {
                    val textSize = this.toFloat()
                    binding.chatTime.changeSize(textSize - 4f)
                    binding.chatQuote.changeSize(textSize)
                    binding.chatName.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
                    binding.chatTv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
                }
            }
            binding.chatTv.initChatMode(LINK_COLOR)
            binding.chatTv.setSelectedStateColor(SELECT_COLOR)
            binding.chatName.maxWidth = itemView.context.maxItemWidth() - dp16
            binding.chatMsgContent.setMaxWidth(itemView.context.maxItemWidth() - dp16)
        }

        override fun chatLayout(
            isMe: Boolean,
            isLast: Boolean,
            isBlink: Boolean,
        ) {
            super.chatLayout(isMe, isLast, isBlink)
            val lp = (binding.chatLayout.layoutParams as ConstraintLayout.LayoutParams)
            if (isMe) {
                lp.horizontalBias = 1f
                if (isLast) {
                    setItemBackgroundResource(
                        binding.chatContentLayout,
                        R.drawable.chat_bubble_reply_me_last,
                        R.drawable.chat_bubble_reply_me_last_night,
                    )
                } else {
                    setItemBackgroundResource(
                        binding.chatContentLayout,
                        R.drawable.chat_bubble_reply_me,
                        R.drawable.chat_bubble_reply_me_night,
                    )
                }
            } else {
                lp.horizontalBias = 0f
                if (isLast) {
                    setItemBackgroundResource(
                        binding.chatContentLayout,
                        R.drawable.chat_bubble_reply_other_last,
                        R.drawable.chat_bubble_reply_other_last_night,
                    )
                } else {
                    setItemBackgroundResource(
                        binding.chatContentLayout,
                        R.drawable.chat_bubble_reply_other,
                        R.drawable.chat_bubble_reply_other_night,
                    )
                }
            }
        }

        private var onItemListener: MessageAdapter.OnItemListener? = null

        fun bind(
            messageItem: MessageItem,
            keyword: String?,
            isLast: Boolean,
            isFirst: Boolean = false,
            hasSelect: Boolean,
            isSelect: Boolean,
            isRepresentative: Boolean,
            onItemListener: MessageAdapter.OnItemListener,
        ) {
            super.bind(messageItem)
            this.onItemListener = onItemListener
            if (hasSelect && isSelect) {
                itemView.setBackgroundColor(SELECT_COLOR)
            } else {
                itemView.setBackgroundColor(Color.TRANSPARENT)
            }

            binding.chatTv.setAutoLinkOnLongClickListener { autoLinkMode, matchedText ->
                when (autoLinkMode) {
                    AutoLinkMode.MODE_URL -> {
                        onItemListener.onUrlLongClick(matchedText)
                    }
                    else -> {
                    }
                }
            }

            binding.chatTv.setAutoLinkOnClickListener { autoLinkMode, matchedText ->
                when (autoLinkMode) {
                    AutoLinkMode.MODE_URL -> {
                        onItemListener.onUrlClick(matchedText)
                    }
                    AutoLinkMode.MODE_MENTION, AutoLinkMode.MODE_BOT -> {
                        onItemListener.onMentionClick(matchedText)
                    }
                    AutoLinkMode.MODE_PHONE -> {
                        onItemListener.onPhoneClick(matchedText)
                    }
                    AutoLinkMode.MODE_EMAIL -> {
                        onItemListener.onEmailClick(matchedText)
                    }
                    else -> {
                    }
                }
            }

            binding.chatTv.setOnLongClickListener {
                if (!hasSelect) {
                    onItemListener.onLongClick(messageItem, absoluteAdapterPosition)
                } else {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                    true
                }
            }

            binding.chatContentLayout.setOnLongClickListener {
                if (!hasSelect) {
                    onItemListener.onLongClick(messageItem, absoluteAdapterPosition)
                } else {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                    true
                }
            }

            binding.chatTv.setOnClickListener {
                if (hasSelect) {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                }
            }

            if (textQuoteGestureListener == null) {
                textQuoteGestureListener = TextQuoteGestureListener(messageItem, onItemListener)
            } else {
                textQuoteGestureListener?.apply {
                    this.messageItem = messageItem
                    this.onItemListener = onItemListener
                }
            }
            binding.chatContentLayout.listener = textQuoteGestureListener

            itemView.setOnLongClickListener {
                if (!hasSelect) {
                    onItemListener.onLongClick(messageItem, absoluteAdapterPosition)
                } else {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                    true
                }
            }

            itemView.setOnClickListener {
                if (hasSelect) {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                }
            }

            if (messageItem.mentions?.isNotBlank() == true) {
                val mentionRenderContext =
                    MentionRenderCache.singleton.getMentionRenderContext(
                        messageItem.mentions,
                    )
                binding.chatTv.renderMessage(messageItem.content, keyword, mentionRenderContext)
            } else {
                binding.chatTv.renderMessage(messageItem.content, keyword)
            }

            val isMe = meId == messageItem.userId
            if (isFirst && !isMe) {
                binding.chatName.visibility = View.VISIBLE
                binding.chatName.text = messageItem.userFullName
                if (messageItem.appId != null) {
                    binding.chatName.setCompoundDrawables(null, null, botIcon, null)
                    binding.chatName.compoundDrawablePadding = 3.dp
                } else {
                    binding.chatName.setCompoundDrawables(null, null, null, null)
                }
                binding.chatName.setTextColor(getColorById(messageItem.userId))
                binding.chatName.setOnClickListener { onItemListener.onUserClick(messageItem.userId) }
            } else {
                binding.chatName.visibility = View.GONE
            }

            if (messageItem.appId != null) {
                binding.chatName.setCompoundDrawables(null, null, botIcon, null)
                binding.chatName.compoundDrawablePadding = 3.dp
            } else {
                binding.chatName.setCompoundDrawables(null, null, null, null)
            }

            binding.chatTime.load(
                isMe,
                messageItem.createdAt,
                messageItem.status,
                messageItem.isPin ?: false,
                isRepresentative = isRepresentative,
                isSecret = messageItem.isSecret(),
            )
            binding.chatContentLayout.setOnClickListener {
                if (!hasSelect) {
                    onItemListener.onQuoteMessageClick(messageItem.messageId, messageItem.quoteId)
                } else {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                }
            }

            val quoteMessage =
                GsonHelper.customGson.fromJson(
                    messageItem.quoteContent,
                    QuoteMessageItem::class.java,
                )
            binding.chatQuote.bind(quoteMessage)

            binding.chatQuote.setOnClickListener {
                if (!hasSelect) {
                    onItemListener.onQuoteMessageClick(messageItem.messageId, messageItem.quoteId)
                } else {
                    onItemListener.onSelect(!isSelect, messageItem, absoluteAdapterPosition)
                }
            }
            chatJumpLayout(binding.chatJump, isMe, messageItem.expireIn, messageItem.expireAt, R.id.chat_layout)
            chatLayout(isMe, isLast)
            attachAction =
                if (messageItem.mentionRead == false) {
                    {
                        blink()
                        RxBus.publish(MentionReadEvent(messageItem.conversationId, messageItem.messageId))
                    }
                } else {
                    null
                }
        }

        private var textQuoteGestureListener: TextQuoteGestureListener? = null

        private class TextQuoteGestureListener(
            var messageItem: MessageItem,
            var onItemListener: MessageAdapter.OnItemListener,
        ) : GestureDetector.SimpleOnGestureListener() {
            override fun onDoubleTap(e: MotionEvent): Boolean {
                onItemListener.onTextDoubleClick(messageItem)
                return true
            }
        }
    }
